﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Core;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using ShakeIt_.Helpers;
using ShakeIt_.Models;
using System.Collections.ObjectModel;
using ShakeIt_.ServiceReference2;

namespace ShakeIt_
{
  
    public partial class nearPage : PhoneApplicationPage
    {
        #region Consts

        /// <value>Default map zoom level.</value>
        private const double DefaultZoomLevel = 18.0;

        /// <value>Maximum map zoom level allowed.</value>
        private const double MaxZoomLevel = 21.0;

        /// <value>Minimum map zoom level allowed.</value>
        private const double MinZoomLevel = 1.0;

        #endregion

        #region Fields

        /// <value>Provides credentials for the map control.</value>
        private readonly CredentialsProvider _credentialsProvider = new ApplicationIdCredentialsProvider(App.Id);

        /// <value>Default location coordinate.</value>
        private GeoCoordinate Location = new GeoCoordinate(31.200833, /*121.429726*/121.43);

        private static readonly GeoCoordinate DefaultLocation = new GeoCoordinate(31.200833, /*121.429726*/121.43);

        public GeoCoordinate GetLocation
        {
            get
            {
                return Location;
            }
            set
            {
                if (Location != value)
                {
                    Location = value;
                    NotifyPropertyChanged("GetLocation");
                }
            }
        }

        private int AddedPushPinCounter;

        /// <value>Collection of pushpins available on map.</value>
        private readonly ObservableCollection<PushpinModel> _pushpins = new ObservableCollection<PushpinModel>
        {
            /*new PushpinModel
            {
                Location = DefaultLocation,
                Icon = new Uri("/Resources/Icons/Pushpins/PushpinLocation.png", UriKind.Relative)
            }*/
        };

        private Pushpin TapedPushpin = null;

        /// <value>Map zoom level.</value>
        private double _zoom;

        /// <value>Map center coordinate.</value>
        private GeoCoordinate _center;

        #endregion

        #region Properties

        public bool HasDirections
        {
            get
            {
                // TODO : Return true only if has directions.

                return true;
            }
        }

        /// <summary>
        /// Gets the credentials provider for the map control.
        /// </summary>
        public CredentialsProvider CredentialsProvider
        {
            get { return _credentialsProvider; }
        }

        /// <summary>
        /// Gets or sets the map zoom level.
        /// </summary>
        public double Zoom
        {
            get { return _zoom; }
            set
            {
                var coercedZoom = Math.Max(MinZoomLevel, Math.Min(MaxZoomLevel, value));
                if (_zoom != coercedZoom)
                {
                    _zoom = value;
                    NotifyPropertyChanged("Zoom");
                }
            }
        }

        /// <summary>
        /// Gets or sets the map center location coordinate.
        /// </summary>
        public GeoCoordinate Center
        {
            get { return _center; }
            set
            {
                if (_center != value)
                {
                    _center = value;
                    NotifyPropertyChanged("Center");
                }
            }
        }

        /// <summary>
        /// Gets a collection of pushpins.
        /// </summary>
        public ObservableCollection<PushpinModel> Pushpins
        {
            get { return _pushpins; }
        }

        #endregion

        #region Tasks

        private void InitializeDefaults()
        {
            // TODO : Initialize default properties.
            CenterLocation();
        }

        private void ChangeMapMode()
        {
            // TODO : Change map view mode.
            if (Map.Mode is AerialMode)
            {
                Map.Mode = new RoadMode();
            }
            else
            {
                Map.Mode = new AerialMode(true);
            }
        }

        private void CenterLocation()
        {
            // Center map to default location.
            Center = Location;

            // Reset zoom default level.
            Zoom = DefaultZoomLevel;
        }

        /*private void CenterPushpinsPopup(Point touchPoint)
        {
            // Reposition the pushpins popup to the center of the touch point.
            Canvas.SetTop(PushpinPopup, 390);
            Canvas.SetLeft(PushpinPopup, 100);
        }*/

        private void CreateNewPushpin(object selectedItem, Point point/*,var activity*/)
        {
            // Translate the map viewport touch point to a geo coordinate.
            GeoCoordinate location;
            Map.TryViewportPointToLocation(point, out location);

            // Use the geo coordinate calculated to add a new pushpin,
            // based on the selected pushpin prototype,
            var pushpinPrototype = selectedItem as PushpinModel;
            PushpinModel pushpin = pushpinPrototype.Clone(location/*,activity*/);

            Pushpins.Add(pushpin);
        }

        private void CreateNewPushpin(_Activity activity)
        {
            // Use the geo coordinate calculated to add a new pushpin,
            // based on the selected pushpin prototype,
            PushpinModel pushpin = new PushpinModel(activity);

            Pushpins.Add(pushpin);
        }

        /*private void Pushpin_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var pushpin = sender as Pushpin;

            
            // Center the map on a pushpin when touched.
            Center = pushpin.Location;
            string name = pushpin.Name;

            CenterPushpinsPopup(e.GetPosition(Map));

            _visualStates.PushpinsState = VisualStates.ShowPushpins;

            // Show pushpins panel.
            
            return;
        }*/

        private void CalculateRoute()
        {
            // TODO : Calculate a route.
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            MapTileLayer bingtileLayer = new MapTileLayer();
            bingtileLayer.Width = 480;
            bingtileLayer.Height = 768;
            TileSource tileSource = new BingChinaTitleSource();
            bingtileLayer.TileSources.Add(tileSource);
            bingtileLayer.Opacity = 0.9;
            Map.Children.Insert(0, bingtileLayer);
            Map.Mode = new MercatorMode();

            SearchContent.Text = Data.searchInput;
        }

        private void PushPin_Loaded(object sender, RoutedEventArgs e)
        {
            if (AddedPushPinCounter < Pushpins.Count)
            {
                PushpinModel pushpinModel = Pushpins[AddedPushPinCounter];
                AddedPushPinCounter++;
                _Activity activity = pushpinModel.Activity;

                Pushpin pushpin = sender as Pushpin;
                Grid grid = (Grid)pushpin.Content;

                TextBlock textblock1 = grid.Children[1] as TextBlock;
                TextBlock textblock2 = grid.Children[2] as TextBlock;
                TextBlock textblock3 = grid.Children[3] as TextBlock;

                textblock1.Text = activity.title;
                textblock2.Text = activity.address;
                textblock3.Text = activity.beginTime.ToString() + "-" + activity.endTime.ToString();
                grid.Children[4].Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(detail_Click);

                PushPinDictionary.Add(pushpinModel, pushpin);
            }
        }

        private void detail_Click(object sender, System.Windows.Input.GestureEventArgs e)
        {
            Image image = sender as Image;
            Grid grid = image.Parent as Grid;
            Pushpin pushpin = grid.Parent as Pushpin;

            for (int index = 0; index < PushPinDictionary.Count; index++)
            {
                if (PushPinDictionary.ElementAt(index).Value == pushpin)
                {
                    Data.res_selected = PushPinDictionary.ElementAt(index).Key.Activity;
                    break;
                }
            }
            this.NavigationService.Navigate(new Uri("/detailPage.xaml", UriKind.Relative));
        }

        private void pushPin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            for (int index = 0; index < PushPinDictionary.Count; index++)
            {
                Grid grid = PushPinDictionary.ElementAt(index).Value.Content as Grid;
                grid.Visibility = System.Windows.Visibility.Collapsed;
            }

            TapedPushpin = sender as Pushpin;
            Grid content = (Grid)TapedPushpin.Content;
            content.Visibility = System.Windows.Visibility.Visible;
            e.Handled = true;
        }

        private void SearchContent_TextChanged(object sender, RoutedEventArgs e)
        {
            Data.searchInput = SearchContent.Text;
            Data.FindActivity();
        }

        private void SwitchToListView_Click(object sender, RoutedEventArgs e)
        {
            if (this.NavigationService.CanGoBack && 
                this.NavigationService.BackStack.ToArray()[0].Source.OriginalString == "/researchresultPage.xaml")
            {
                this.NavigationService.GoBack();
            }else
                this.NavigationService.Navigate(new Uri("/researchresultPage.xaml", UriKind.Relative));
        }

        private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            GetLocation.Longitude = DefaultLocation.Longitude + e.NewValue;
            Data.currentLocation.Longitude = GetLocation.Longitude;
            displayUser();
        }

        private void slider2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            GetLocation.Latitude = DefaultLocation.Latitude + e.NewValue;
            Data.currentLocation.Latitude = GetLocation.Latitude;
            displayUser();
        }

        private void displayUser()
        {
            //pushpin1. = Map.LocationToViewportPoint(pushpin1.Location);
            //Center.Longitude += 0.001;
            //Center.Longitude -= 0.001;
        }

        #endregion

        private void pushpin1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {

        }
    }
    public partial class nearPage : INotifyPropertyChanged
    {
        #region Fields

        /// <value>Helper for handling mouse (touch) events.</value>
        private readonly TouchBehavior _touchBehavior;

        /// <value>Helper for handling visual states.</value>
        private readonly VisualStates _visualStates;

        private Dictionary<PushpinModel, Pushpin> PushPinDictionary = new Dictionary<PushpinModel,Pushpin>();

        #endregion

        #region Ctor

        public nearPage()
        {
            InitializeDefaults();
            InitializeComponent();

            SearchContent.Text = Data.searchInput;

            _touchBehavior = new TouchBehavior(this);
            _touchBehavior.Tap += touchBehavior_Tap;
            _touchBehavior.Move += touchBehavior_Move;
            _touchBehavior.Hold += touchBehavior_Hold;

            _visualStates = new VisualStates(this);

            DataContext = this;

            displayActivity(Data.result);
            Data.proxy.FindActivityByLocationCompleted += new EventHandler<FindActivityByLocationCompletedEventArgs>(FindActivityCompleted);
            Data.proxy.FindActivityByLocationAndKeywordCompleted += new EventHandler<FindActivityByLocationAndKeywordCompletedEventArgs>(FindActivityKeywordCompleted);
        }

        #endregion

        #region Event Handlers

        private void FindActivityCompleted(object sender, FindActivityByLocationCompletedEventArgs e)
        {
            displayActivity(Data.result);
        }

        private void FindActivityKeywordCompleted(object sender, FindActivityByLocationAndKeywordCompletedEventArgs e)
        {
            displayActivity(Data.result);
        }

        private void displayActivity(List<_Activity> res)
        {
            Pushpins.Clear();
            PushPinDictionary.Clear();
            AddedPushPinCounter = 0;
            foreach (_Activity acti in res)
            {
                CreateNewPushpin(acti);
            }
        }

        private void ButtonLocation_Click(object sender, EventArgs e)
        {
            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;

            CenterLocation();
        }

        private void ButtonRoute_Click(object sender, EventArgs e)
        {
            // Display or hide route panel.
            if (_visualStates.RouteState == VisualStates.HideRoute)
            {
                _visualStates.RouteState = VisualStates.ShowRoute;
            }
            else
            {
                _visualStates.RouteState = VisualStates.HideRoute;
            }

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonDirections_Click(object sender, EventArgs e)
        {
            // Display or hide directions panel.
            if (_visualStates.DirectionsState == VisualStates.HideDirections)
            {
                if (HasDirections)
                {
                    _visualStates.DirectionsState = VisualStates.ShowDirections;
                }
            }
            else
            {
                _visualStates.DirectionsState = VisualStates.HideDirections;
            }

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonMode_Click(object sender, EventArgs e)
        {
            ChangeMapMode();

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void touchBehavior_Tap(object sender, TouchBehaviorEventArgs e)
        {
            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;

            if (TapedPushpin != null)
            {
                for (int index = 0; index < PushPinDictionary.Count; index++)
                {
                    Grid grid = PushPinDictionary.ElementAt(index).Value.Content as Grid;
                    grid.Visibility = System.Windows.Visibility.Collapsed;
                }

                TapedPushpin = null;
            }
        }

        private void touchBehavior_Move(object sender, TouchBehaviorEventArgs e)
        {
            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;

            if (TapedPushpin != null)
            {
                for (int index = 0; index < PushPinDictionary.Count; index++)
                {
                    Grid grid = PushPinDictionary.ElementAt(index).Value.Content as Grid;
                    grid.Visibility = System.Windows.Visibility.Collapsed;
                }

                TapedPushpin = null;
            }
        }

        private void touchBehavior_Hold(object sender, TouchBehaviorEventArgs e)
        {
            //CenterPushpinsPopup(e.TouchPoint);

            // Show pushpins panel.
           // _visualStates.PushpinsState = VisualStates.ShowPushpins;
        }

        private void ButtonGo_Click(object sender, RoutedEventArgs e)
        {
            CalculateRoute();

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonZoomIn_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Zoom += 1;

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonZoomOut_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Zoom -= 1;

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ListBoxPushpinCatalog_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selector = sender as Selector;
            if (selector == null || selector.SelectedItem == null)
            {
                return;
            }

            //CreateNewPushpin(selector.SelectedItem, _touchBehavior.LastTouchPoint);
            if (selector.SelectedIndex.ToString() == "0")
            {
                selector.SelectedItem = null;
                this.NavigationService.Navigate(new Uri("/createPage.xaml", UriKind.Relative));
            }

            // Reset the selected item so we can pick it again next time.
            

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        #endregion

        #region Privates

        /// <summary>
        /// Hides the route view and display the directions view.
        /// </summary>
        private void ShowDirectionsView()
        {
            _visualStates.RouteState = VisualStates.HideRoute;

            if (HasDirections)
            {
                _visualStates.DirectionsState = VisualStates.ShowDirections;
            }
        }

        #endregion

        #region Property Changed

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        #endregion

        #region Visual States
        /// <summary>
        /// An internal helper class for handling MainPage visual state transitions.
        /// </summary>
        private class VisualStates
        {
            #region Predefined Visual States
            // Route States
            public const string ShowRoute = "ShowRoute";
            public const string HideRoute = "HideRoute";

            // Directions States
            public const string ShowDirections = "ShowDirections";
            public const string HideDirections = "HideDirections";

            // Pushpins States
            public const string ShowPushpins = "ShowPushpins";
            public const string HidePushpins = "HidePushpins";
            #endregion

            #region Fields
            private readonly Control _control;
            private string _routeState = VisualStates.HideRoute;
            private string _directionsState = VisualStates.HideDirections;
            private string _pushpinsState = VisualStates.HidePushpins;
            #endregion

            #region Properties
            /// <summary>
            /// Change the route panel visual state.
            /// </summary>
            public string RouteState
            {
                get { return _routeState; }
                set
                {
                    if (_routeState != value)
                    {
                        _routeState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }

            /// <summary>
            /// Change the directions panel visual state.
            /// </summary>
            public string DirectionsState
            {
                get { return _directionsState; }
                set
                {
                    if (_directionsState != value)
                    {
                        _directionsState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }

            /// <summary>
            /// Change the pushpins popup visual state.
            /// </summary>
            public string PushpinsState
            {
                get { return _pushpinsState; }
                set
                {
                    if (_pushpinsState != value)
                    {
                        _pushpinsState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }
            #endregion

            #region Ctor
            /// <summary>
            /// Initializes a new instance of this class.
            /// </summary>
            /// <param name="control">The target control.</param>
            public VisualStates(Control control)
            {
                _control = control;
            }
            #endregion
        }
        #endregion



    }
}